#! /usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2020-04-02 22:34
# @Author : youngchaolin

# 函数传参：让函数封装这个功能
# 函数的参数，分为实参，和形参


# 函数执行传递的参数（男，女，人妖），是实际参数，函数定义里的那个参数（sex），就是形参
def my_print(sex):
    print('我的性别是%s' % (sex))


my_print('男')
my_print('女')
my_print('人妖')


# 实参和形参，从左至右，一一对应
# 1 位置传参
def data_print(sex, age, hobby):
    print('我的性别是%s,年龄是%s,爱好是%s' % (sex, age, hobby))


data_print('男', '33', '女')


# 定义一个函数，比较其中较大的值返回
def my_max(a, b):
    if a >= b:
        return a
    else:
        return b


print(my_max(100, 250))
print(my_max(1000, 250))


# 三元运算符
def my_max_2(a, b):
    return a if a > b else b


print(my_max_2(520, 1314))

# 2 关键字参数
data_print(sex='人妖', hobby='男', age=45)


# 传入两个字符串参数，将两个参数拼接完成后形成的结果返回
def combine(s1, s2):
    return s1 + s2


print(combine('hello', 'kitty'))

# 3 混合传参
# 位置参数，一定要在关键字参数的前面
data_print('男', hobby='足球', age=45)

'''
实参角度：
    1 位置参数，需要和形参顺序一一对应
    2 关键字参数，顺序不一定，但是要一一对应
    3 混合参数，位置参数一定要在关键字参数的前面
'''


# 形参的角度
# 1 位置参数，跟实参的角度一样

# 传入一个列表，如果列表的长度大于2，那么仅仅保留前两个长度的内容返回
def get_list(li):
    if len(li) > 2:
        return li[0:2]
    else:
        return li


def get_list_2(li):
    return li[0:2] if len(li) > 2 else li


# 不管长度是否大于2，切片都可以
def get_list_3(li):
    return li[0:2]


print(get_list([1, 2, 3, 4]))
print(get_list([1]))

print(get_list_2([1, 2, 3, 4]))

print(get_list_3([1]))


# 2 默认参数，可以在行参中定义默认参数，默认参数需要定义在后面
# open方法的mode默认就是r，因为方法默认定义了mode为r，这就是默认行参
# open()

#年龄默认25
def data_print_2(sex, hobby, age=25):
    print('我的性别是%s,年龄是%s,爱好是%s' % (sex, age, hobby))


data_print_2('男', '足球')
# 如果传入age，则覆盖默认
data_print_2('男', '足球', age=45)


# 3 万能参数之*args和**kwargs
# *args类似java中的可变参数，但是python的参数类型不定，最终会聚合成一个元祖，而java中是数组
# 参数名，约定俗称为args，外层使用*包裹，实现集合，变成元祖
def my_print(*args):
    print('天皇巨星：%s,%s,%s,%s' % args)


my_print('messi', 'ronald', 'herry', 'kaka')
# 如果只传入3个参数，会报错
# my_print('messi', 'ronald', 'herry')


# **kwargs
# **kwargs 聚合关键字参数为一个字典，存储到kwargs中
def test(**kwargs):
    print(kwargs)
# 打印结果为字典
test(name='clyang',age=28,hobby='football')

# 以下方法，可以接收任意类型的参数，位置参数，被*args接收，关键字参数，被**kwargs接收
def func(*args,**kwargs):
    print(args)
    print(kwargs)
# 测试传入位置参数和关键字参数
func(1,2,3,name='messi',age=34,score=33)

# (1, 2, 3) 打印结果为元祖
# {'name': 'messi', 'age': 34, 'score': 33} 打印结果为字典


# 写一个函数，计算传入的所有数字的和
def get_sum(*args):
    return sum(args)

print(get_sum(1, 2, 3, 4, 5))

# 形参角度的参数顺序，包括位置参数、默认参数、*args、**kwargs
# 顺序为位置参数、*args、默认参数
def sequence(a,b,*args,c='男'):
    print(a,b)
    print(c)
    print(args)

sequence(1,2,3,4,5)
sequence(1,2,3,4,5,c='人妖')

# 顺序为位置参数、*args、默认参数、**kwargs
def sequence_2(a,b,*args,c='男',**kwargs):
    print(a, b)
    print(c)
    print(args)
    print(kwargs)

sequence_2(1,2,3,4,5,name='messi',age=28)
sequence_2(1,2,3,4,5,name='messi',age=28,c='女')
sequence_2(1,2,3,4,5,c='人妖',name='messi',age=28)

# 4 仅限关键字参数
# 如下处于*args和**kwargs之间的参数d，就是仅限关键字参数
def sequence_3(a,b,*args,c='男',d,**kwargs):
    print(a, b)
    print(c)
    print(d)
    print(args)
    print(kwargs)

sequence_3(1,2,3,4,5,name='messi',age=28,d='仅限关键字参数')

# 5 行参的最终顺序：位置参数、*args、默认参数、仅限关键字参数、**kwargs。其中默认参数和仅限关键字参数位置可以互换

# *或**，在函数使用时，代表打散。而在函数定义时，代表聚合
def func_2(*args):
    print(args)

func_2([1,2],[3,4])
func_2(*[1,2],*[3,4]) # 等效func_2(1, 2, 3, 4)
func_2(1, 2, 3, 4)

def func_3(**kwargs):
    print(kwargs)

func_3(name='messi',age=28)
func_3(**{'name':'messi'},**{'age':28}) # 等效func_3(name='messi',age=28)







